home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
intrlib1.zip
/
PU_QUERY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-22
|
27KB
|
713 lines
/******************************************************************************
* Iteraction library - pop up queries. *
* *
* Written by Gershon Elber, Oct. 1990 *
*******************************************************************************
* Type of queries currently supported: *
* 1. Continue query - informative pop up message. Wait for the user. *
* 2. Yes/No query - pop up question. Wait for yes/no from the user. *
* 3. Line query - pop up a messgae. Wait for the user to type a full line. *
*******************************************************************************
* History: *
* 3 Oct 90 - Version 1.0 by Gershon Elber. *
******************************************************************************/
#include <string.h>
#include <stdio.h>
#include "intr_loc.h"
#include "intr_gr.h"
#define MIN_CONTINUE_QUERY_WIDTH 150
#define CONTINUE_QUERY_HEIGHT 90
#define CONTINUE_STR_HEIGHT 20
#define CONTINUE_STR_WIDTH 80
#define MIN_CONTINUE2_QUERY_WIDTH 150
#define CONTINUE2_QUERY_HEIGHT 40
#define MIN_YES_NO_QUERY_WIDTH 180
#define YES_NO_QUERY_HEIGHT 90
#define YES_NO_STR_HEIGHT 20
#define YES_NO_STR_WIDTH 50
#define MIN_LINE_QUERY_WIDTH 150
#define LINE_QUERY_HEIGHT 70
#define LINE_WINDOW_LEN 22
#define LIST_QUERY_BORDER 8
#ifdef DJGCC
#define LIST_QUERY_BASE_LINE 16
#else
#define LIST_QUERY_BASE_LINE 12
#endif /* DJGCC */
static int GRLastColor = 0; /* GR Color set before query. */
static IntrBType HasHeader = FALSE;
static void QueryProlog(int WindowID, int QueryWidth, int QueryHeight,
IntrCursorShapeStruct *Cursor, IntrColorType FrameWidth,
IntrColorType FrameColor, IntrColorType BackColor,
int *Xmin, int *Ymin, int *Xmax, int *Ymax,
IntrScrlBarType ScrlBar);
static void QueryEpilog(IntrCursorShapeStruct *Cursor);
static int MatchPosition(int x, int y, int Top, int Left,
int Bottom, int Right, int Space, int ItemHeight);
static void ListQueryDrawItems(char **StrEntries, int SizeOfEntry,
int NumOfEntries,
int FirstDisplayed, int NumOfDisplayedEntries,
int Left, int Top, int Right, int Bottom,
IntrColorType BackColor, IntrColorType ForeColor);
/****************************************************************************
* Do all common to all queries on entry. *
* Attempt will be made to place the message in the middle of the specified *
* window windowID if possible, or middle of screen if WindowID = 0. *
* Width and Height specifies the size of the query window and FrameWidth *
* specifies its FrameWidth. FrameColor and BackColor set the colors. *
****************************************************************************/
static void QueryProlog(int WindowID, int QueryWidth, int QueryHeight,
IntrCursorShapeStruct *Cursor, IntrColorType FrameWidth,
IntrColorType FrameColor, IntrColorType BackColor,
int *Xmin, int *Ymin, int *Xmax, int *Ymax,
IntrScrlBarType ScrlBar)
{
IntrBBoxStruct *BBox;
int QueryCenterX, QueryCenterY;
/* Save current graphic state. */
if (Cursor != NULL) {
IntrPushCursorType();
IntrSetCursorType(Cursor);
}
GRPushViewPort();
_GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);
GRPushTextSetting();
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_BOTTOM);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
GRLastColor = GRGetColor();
/* Find center of query prefered position and find BBox for query. */
if (WindowID > 0) {
BBox = IntrWndwGetBBox(WindowID);
QueryCenterX = (BBox -> Xmax + BBox -> Xmin) >> 1;
QueryCenterY = (BBox -> Ymax + BBox -> Ymin) >> 1;
}
else
switch (WindowID) {
case INTR_WNDW_PLACE_LEFT:
QueryCenterX = GRScreenMaxX >> 2;
QueryCenterY = GRScreenMaxY >> 1;
break;
case INTR_WNDW_PLACE_RIGHT:
QueryCenterX = (GRScreenMaxX >> 1) + (GRScreenMaxX >> 2);
QueryCenterY = GRScreenMaxY >> 1;
break;
case INTR_WNDW_PLACE_CENTER:
default:
QueryCenterX = GRScreenMaxX >> 1;
QueryCenterY = GRScreenMaxY >> 1;
break;
}
*Xmin = QueryCenterX - (QueryWidth >> 1);
*Ymin = QueryCenterY - (QueryHeight >> 1);
*Xmax = *Xmin + QueryWidth;
*Ymax = *Ymin + QueryHeight;
_IntrBoundBBox(Xmin, Ymin, Xmax, Ymax, FrameWidth); /* To screen coords. */
_IntrWndwDrawFrame(*Xmin, *Xmax, *Ymin, *Ymax, FrameWidth,
FrameColor, TRUE, FrameColor, INTR_SCRLBAR_NONE,
FrameColor, ScrlBar, TRUE);
IntrAllocColor(BackColor, INTR_INTENSITY_HIGH);
GRSBar(*Xmin, *Ymin, *Xmax, *Ymax);
}
/****************************************************************************
* Pop current graphic state. *
****************************************************************************/
static void QueryEpilog(IntrCursorShapeStruct *Cursor)
{
if (_IntrSaveBelow) {
_IntrRestoreWindow();
if (HasHeader) {
_IntrRestoreWindow();
HasHeader = FALSE;
}
}
GRPopViewPort();
GRPopTextSetting();
GRSetColor(GRLastColor);
if (Cursor != NULL)
IntrPopCursorType();
}
/****************************************************************************
* Perform simple clipping and translation to make sure entire bbox is in *
* the screen boundary. *
****************************************************************************/
void _IntrBoundBBox(int *Xmin, int *Ymin, int *Xmax, int *Ymax, int Width)
{
if (*Xmin < Width) {
*Xmax -= *Xmin - Width;
*Xmin = Width;
}
if (*Xmax > GRScreenMaxX - Width) {
*Xmin -= *Xmax - GRScreenMaxX + Width;
*Xmax = GRScreenMaxX - Width;
}
if (*Ymin < Width) {
*Ymax -= *Ymin - Width;
*Ymin = Width;
}
if (*Ymax > GRScreenMaxY - Width) {
*Ymin -= *Ymax - GRScreenMaxY + Width;
*Ymax = GRScreenMaxY - Width;
}
}
/****************************************************************************
* Routine to display one string and return after a continue button has been *
* pressed. Used to inform the user on some status. *
* Attempt will be made to place the message in the middle of the specified *
* window if possible, or middle of screen if WindowID = 0. *
****************************************************************************/
void IntrQueryContinue(char *Question,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
IntrColorType XorColor,
int FrameWidth,
IntrCursorShapeStruct *Cursor,
int WindowID)
{
IntrEventType Event;
int x, y, TextWidth, NewMatch, Color, QueryWidth, QueryHeight,
Xmin, Ymin, Xmax, Ymax, ContXmin, ContYmin, ContXmax, ContYmax,
Exit = FALSE,
Match = -1;
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
TextWidth = GRGetTextWidth(Question);
QueryWidth = MAX(TextWidth + 10, MIN_CONTINUE_QUERY_WIDTH);
QueryHeight = CONTINUE_QUERY_HEIGHT;
GRPopTextSetting();
QueryProlog(WindowID, QueryWidth, QueryHeight, Cursor, FrameWidth,
FrameColor, BackColor, &Xmin, &Ymin, &Xmax, &Ymax,
INTR_SCRLBAR_NONE);
/* Compute spaces between the Continue button and question. */
y = ((Ymax - Ymin) - CONTINUE_STR_HEIGHT - GRGetTextHeight(Question)) / 3;
/* Draw the "continue" button. */
ContXmin = (Xmin + Xmax - CONTINUE_STR_WIDTH) >> 1;
ContXmax = (Xmin + Xmax + CONTINUE_STR_WIDTH) >> 1;
ContYmax = Ymax - y;
ContYmin = ContYmax - CONTINUE_STR_HEIGHT;
_IntrWndwDrawFrame(ContXmin, ContXmax, ContYmin, ContYmax, FrameWidth,
FrameColor, FALSE, FrameColor, INTR_SCRLBAR_NONE,
FrameColor, INTR_SCRLBAR_NONE, TRUE);
IntrAllocColor(BackColor, INTR_INTENSITY_LOW);
GRSBar(ContXmin, ContYmin, ContXmax, ContYmax);
Color = IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH);
GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
GRSTextShadow((ContXmin + ContXmax) >> 1, (ContYmin + ContYmax) >> 1,
Color, "Continue");
/* Put the question in: */
GRSTextShadow((Xmin + Xmax) >> 1, Ymin + y, Color, Question);
/* Put the mouse on the middle of the CONTINUE box: */
x = GRCurrentCursorX = (ContXmin + ContXmax) >> 1;
y = GRCurrentCursorY = (ContYmin + ContYmax) >> 1;
Event = INTR_EVNT_MOVE;/* Emulate move event, and test current position. */
while (!Exit) {
switch (Event) {
case INTR_EVNT_KEY:
if (x == 'c' || x == 'C') {
Match = 1;
Exit = TRUE;
break;
}
break;
case INTR_EVNT_SELECT:
if (Match >= 0)
Exit = TRUE;
else {
GRTone(1000, 100); /* Do some noise... */
GRTone( 300, 200);
}
break;
case INTR_EVNT_ABORT: /* Ignored. */
GRTone(1000, 100); /* Do some noise... */
GRTone( 300, 200);
break;
case INTR_EVNT_MOVE:
if (x >= ContXmin && x <= ContXmax &&
y >= ContYmin && y <= ContYmax)
NewMatch = 1;
else
NewMatch = -1; /* No match. */
if (NewMatch != Match) {
IntrAllocColor(XorColor, INTR_INTENSITY_VHIGH);
/* If something was selected before - uninvert it: */
if (Match == 1)
GRXORRectangle(ContXmin, ContYmin, ContXmax, ContYmax);
Match = NewMatch;
/*Invert new selection if there is one: */
if (Match == 1)
GRXORRectangle(ContXmin, ContYmin, ContXmax, ContYmax);
}
break;
}
if (!Exit) Event = IntrGetEventWait(&x, &y);
}
QueryEpilog(Cursor);
}
/****************************************************************************
* Same as continue but call ExecFunc instead of event waiting. *
****************************************************************************/
void IntrQueryContinue2(char *Question,
void (* ExecFunc)(void),
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
int FrameWidth,
IntrCursorShapeStruct *Cursor,
int WindowID)
{
int TextWidth, QueryWidth, QueryHeight, Xmin, Ymin, Xmax, Ymax;
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
TextWidth = GRGetTextWidth(Question);
QueryWidth = MAX(TextWidth + 10, MIN_CONTINUE2_QUERY_WIDTH);
QueryHeight = CONTINUE2_QUERY_HEIGHT;
GRPopTextSetting();
QueryProlog(WindowID, QueryWidth, QueryHeight, Cursor,
FrameWidth, FrameColor, BackColor, &Xmin, &Ymin, &Xmax, &Ymax,
INTR_SCRLBAR_NONE);
/* Put the question in: */
GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);
GRSTextShadow((Xmin + Xmax) >> 1, (Ymin + Ymax) >> 1,
IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH), Question);
ExecFunc();
QueryEpilog(Cursor);
}
/****************************************************************************
* Routine to display one string and return TRUE if YES is selected FALSE if *
* NO. select must be made using the Select key, and Abort key is ignored. *
* Attempt will be made to place the message in the middle of the specified *
* window if possible, or middle of screen if WindowID = 0. *
****************************************************************************/
IntrBType IntrQueryYesNo(char *Question,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
IntrColorType XorColor,
int FrameWidth,
IntrCursorShapeStruct *Cursor,
int WindowID)
{
IntrEventType Event;
int x, y, TextWidth, Color, NewMatch, QueryWidth, QueryHeight,
Xmin, Ymin, Xmax, Ymax, Dx4, YesXmin, YesYmin, YesXmax, YesYmax,
NoXmin, NoYmin, NoXmax, NoYmax,
Exit = FALSE,
Match = -1;
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
TextWidth = GRGetTextWidth(Question);
QueryWidth = MAX(TextWidth + 10, MIN_YES_NO_QUERY_WIDTH);
QueryHeight = YES_NO_QUERY_HEIGHT;
GRPopTextSetting();
QueryProlog(WindowID, QueryWidth, QueryHeight, Cursor,
FrameWidth, FrameColor, BackColor, &Xmin, &Ymin, &Xmax, &Ymax,
INTR_SCRLBAR_NONE);
Dx4 = (Xmax - Xmin) >> 2;
y = ((Ymax - Ymin) - YES_NO_STR_HEIGHT - GRGetTextHeight(Question)) / 3;
/* Draw the "yes" button. */
YesXmin = Xmin + Dx4 - (YES_NO_STR_WIDTH >> 1);
YesXmax = Xmin + Dx4 + (YES_NO_STR_WIDTH >> 1);
YesYmax = Ymax - y;
YesYmin = YesYmax - YES_NO_STR_HEIGHT;
_IntrWndwDrawFrame(YesXmin, YesXmax, YesYmin, YesYmax, FrameWidth,
FrameColor, FALSE, FrameColor, INTR_SCRLBAR_NONE,
FrameColor, INTR_SCRLBAR_NONE, TRUE);
IntrAllocColor(BackColor, INTR_INTENSITY_LOW);
GRSBar(YesXmin, YesYmin, YesXmax, YesYmax);
Color = IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH);
GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
GRSTextShadow((YesXmin + YesXmax) >> 1, (YesYmin + YesYmax) >> 1,
Color, "Yes");
/* Draw the "no" button. */
NoXmin = Xmax - Dx4 - (YES_NO_STR_WIDTH >> 1);
NoXmax = Xmax - Dx4 + (YES_NO_STR_WIDTH >> 1);
NoYmax = Ymax - y;
NoYmin = NoYmax - YES_NO_STR_HEIGHT;
_IntrWndwDrawFrame(NoXmin, NoXmax, NoYmin, NoYmax, FrameWidth,
FrameColor, FALSE, FrameColor, INTR_SCRLBAR_NONE,
FrameColor, INTR_SCRLBAR_NONE, TRUE);
IntrAllocColor(BackColor, INTR_INTENSITY_LOW);
GRSBar(NoXmin, NoYmin, NoXmax, NoYmax);
GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
GRSTextShadow((NoXmin + NoXmax) >> 1, (NoYmin + NoYmax) >> 1, Color, "No");
/* Put the question in: */
GRSTextShadow((Xmin + Xmax) >> 1, Ymin + y, Color, Question);
/* Put the mouse on the middle of the Yes box: */
x = GRCurrentCursorX = (YesXmin + YesXmax) >> 1;
y = GRCurrentCursorY = (YesYmin + YesYmax) >> 1;
Event = INTR_EVNT_MOVE;/* Emulate move event, and test current position. */
while (!Exit) {
switch (Event) {
case INTR_EVNT_KEY:
if (x == 'y' || x == 'Y') {
Match = 1;
Exit = TRUE;
break;
}
if (x == 'n' || x == 'N') {
Match = 0;
Exit = TRUE;
break;
}
break;
case INTR_EVNT_SELECT:
if (Match >= 0)
Exit = TRUE;
else {
GRTone(1000, 100); /* Do some noise... */
GRTone( 300, 200);
}
break;
case INTR_EVNT_ABORT: /* Ignored. */
GRTone(1000, 100); /* Do some noise... */
GRTone( 300, 200);
break;
case INTR_EVNT_MOVE:
if (x >= YesXmin && x <= YesXmax &&
y >= YesYmin && y <= YesYmax)
NewMatch = 1;
else if (x >= NoXmin && x <= NoXmax &&
y >= NoYmin && y <= NoYmax)
NewMatch = 0;
else
NewMatch = -1; /* No match. */
if (NewMatch != Match) {
IntrAllocColor(XorColor, INTR_INTENSITY_VHIGH);
/* If something was selected before - uninvert it: */
if (Match == 0)
GRXORRectangle(NoXmin, NoYmin, NoXmax, NoYmax);
else if (Match == 1)
GRXORRectangle(YesXmin, YesYmin, YesXmax, YesYmax);
Match = NewMatch;
/* If something is selected now - invert it: */
if (Match == 0)
GRXORRectangle(NoXmin, NoYmin, NoXmax, NoYmax);
else if (Match == 1)
GRXORRectangle(YesXmin, YesYmin, YesXmax, YesYmax);
}
break;
}
if (!Exit) Event = IntrGetEventWait(&x, &y);
}
QueryEpilog(Cursor);
return Match;
}
/****************************************************************************
* Routine to display one string and wait for input string, which is *
* placed in given buffer. String may be non NULL to begin with. *
* Attempt will be made to place the message in the middle of the specified *
* window if possible, or middle of screen if WindowID = 0. *
* Return the Buffer address. *
****************************************************************************/
char *IntrQueryLine(char *Question,
char *Buffer,
int BufferSize,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
int FrameWidth,
int WindowID)
{
int x, y, LineWindowLen, TextWidth, QueryWidth, QueryHeight, Color,
Xmin, Ymin, Xmax, Ymax;
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
TextWidth = GRGetTextWidth(Question);
QueryWidth = MAX(TextWidth + 10, MIN_LINE_QUERY_WIDTH);
QueryHeight = LINE_QUERY_HEIGHT;
GRPopTextSetting();
QueryProlog(WindowID, QueryWidth, QueryHeight, NULL,
FrameWidth, FrameColor, BackColor, &Xmin, &Ymin, &Xmax, &Ymax,
INTR_SCRLBAR_NONE);
/* Put underline for input line: */
x = Xmin + 20;
y = Ymax - ((Ymax - Ymin) >> 2) - 10;
GRSetTextJustify(GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER);
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
Color = IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH);
/* Put the question in: */
GRSTextShadow((Xmin + Xmax) >> 1, Ymin + ((Ymax - Ymin) >> 2), Color,
Question);
LineWindowLen = (Xmax - Xmin - 40) / GRGetTextWidth("M");
GRSLine(x,
y + GRGetTextHeight("M") + 3,
x + GRGetTextWidth("M") * LineWindowLen,
y + GRGetTextHeight("M") + 3);
GRGetGraphicLine(0, x, y, Buffer, BufferSize, LineWindowLen,
IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH),
IntrAllocColor(BackColor, INTR_INTENSITY_HIGH));
QueryEpilog(NULL);
return Buffer;
}
/****************************************************************************
* Routine to attempt to match given location with one of the elements in *
* items displayed. Item are displayed from Top to Bottom, Left to Right. *
* Item is placed with Space between them and border, and has ItemHeight *
* height. *
* Returns the index that matches, or -1 if No match. *
****************************************************************************/
static int MatchPosition(int x, int y, int Top, int Left,
int Bottom, int Right, int Space, int ItemHeight)
{
int CurrentY, i;
/* Fast clipping if cursor is not in the menu at all. */
if (x <= Left || x >= Right || y <= Top || y >= Bottom) return -1;
for (i = 0, CurrentY = Top;
CurrentY < Bottom;
CurrentY += Space, i++) {
if (CurrentY <= y && CurrentY + ItemHeight >= y) return i;
}
return -1;
}
/****************************************************************************
* Routine to display a list of items and pick one of them. Functionality *
* of this query is very much like a pop up menu, but number of items is *
* virtually unlimited - the user can scroll between items. *
* Header is an optional header for the list query. *
* StrEntries may be an array of (char *) in which SizeOfEntry is 0 or may *
* be of type (char *) itself and it will hold all items linearly, each of *
* size SizeOfEntry. *
* NumOfEntries holds number of entries in StrEntries - List size. *
* NumOfDisplayedEntries holds # of entries to be simultaneously displayed. *
* XXXXColor controls different colors to be used. *
* FrameWidth sets the frame drawn for the list query width. *
* Cursor may specify a new cursor to use. *
* Menu will be poped in the middle of the screen if WindowID == 0 or in the *
* middle of the specified WindowID. In all cases the menu will be moved so *
* it will be all visible. *
****************************************************************************/
int IntrQueryList(char *Header,
char **StrEntries,
int SizeOfEntry,
int NumOfEntries,
int NumOfDisplayedEntries,
IntrColorType FrameColor,
IntrColorType BackColor,
IntrColorType ForeColor,
IntrColorType XorColor,
int FrameWidth,
IntrCursorShapeStruct *Cursor,
int WindowID)
{
int i, MaxLen, QueryWidth, QueryHeight, Xmin, Xmax, Ymin, Ymax, NewIndex,
x, y, Event, RetVal, ListLeft, ListTop, ListRight, ListBottom,
MatchIndex = -1,
FirstDisplayed = 0;
IntrBType
Exit = FALSE;
IntrRType
DisplayedFraction = ((IntrRType) NumOfDisplayedEntries) / NumOfEntries,
RelativePosition = 0.0;
char
*String = (char *) StrEntries;
/* Find width and height of list query using number of items and their */
/* maximum entry string length. */
if (SizeOfEntry == 0) { /* Its an array of pointers to strings. */
for (i = MaxLen = 0; i < NumOfEntries; i++)
if (MaxLen < strlen(StrEntries[i]))
MaxLen = strlen(StrEntries[i]);
}
else {
for (i = MaxLen = 0; i < NumOfEntries; i++)
if (MaxLen < strlen(&String[i * SizeOfEntry]))
MaxLen = strlen(&String[i * SizeOfEntry]);
}
GRPushTextSetting();
GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
QueryWidth = GRGetTextWidth("M") * MaxLen + (LIST_QUERY_BORDER << 1);
QueryHeight = NumOfDisplayedEntries * LIST_QUERY_BASE_LINE +
(LIST_QUERY_BORDER << 1);
GRPopTextSetting();
QueryProlog(WindowID, QueryWidth, QueryHeight, Cursor,
FrameWidth, FrameColor, BackColor, &Xmin, &Ymin, &Xmax, &Ymax,
INTR_SCRLBAR_LEFT);
MatchIndex = -1; /* No match == -1. */
ListLeft = Xmin + LIST_QUERY_BORDER;
ListTop = Ymin + LIST_QUERY_BORDER;
ListRight = Xmax - LIST_QUERY_BORDER;
ListBottom = Ymax - LIST_QUERY_BORDER;
ListQueryDrawItems(StrEntries, SizeOfEntry, NumOfEntries,
FirstDisplayed, NumOfDisplayedEntries,
ListLeft, ListTop, ListRight, ListBottom,
BackColor, ForeColor);
if (Header != NULL) {
HasHeader = TRUE;
_IntrWndwPutNameHeader(Xmin - FrameWidth - _INTR_SCROLL_BAR_WIDTH - 1,
Xmax + FrameWidth,
Ymin - FrameWidth - 2,
FrameWidth, Header, TRUE, FrameColor,
ForeColor, BackColor, TRUE);
}
_IntrUpdateScrollBar(Xmin - _INTR_SCROLL_BAR_WIDTH - 1, Ymin,
Xmin - 1, Ymax,
RelativePosition, DisplayedFraction, TRUE, ForeColor);
Event = INTR_EVNT_MOVE;/* Emulate move event, and test current position. */
x = GRCurrentCursorX = (ListLeft + ListRight) >> 1;
y = GRCurrentCursorY = (ListTop + ListBottom) >> 1;
while (!Exit) {
switch (Event) {
case INTR_EVNT_SELECT:
/* We are on list item - need to return its index. */
if (MatchIndex >= 0) {
RetVal = MatchIndex + FirstDisplayed;
Exit = TRUE;
}
else if (x >= Xmin - _INTR_SCROLL_BAR_WIDTH && x <= Xmin &&
y >= Ymin && y <= Ymax) {
RelativePosition = ((IntrRType) (y - Ymin)) /
(Ymax - Ymin);
FirstDisplayed = (int) (RelativePosition * NumOfEntries);
_IntrUpdateScrollBar(Xmin - _INTR_SCROLL_BAR_WIDTH - 1, Ymin,
Xmin - 1, Ymax,
RelativePosition, DisplayedFraction,
TRUE, ForeColor);
ListQueryDrawItems(StrEntries, SizeOfEntry, NumOfEntries,
FirstDisplayed, NumOfDisplayedEntries,
ListLeft, ListTop, ListRight, ListBottom,
BackColor, ForeColor);
}
break;
case INTR_EVNT_ABORT:
RetVal = -1;
Exit = TRUE;
break;
case INTR_EVNT_MOVE:
IntrAllocColor(XorColor, INTR_INTENSITY_VHIGH);
NewIndex = MatchPosition(x, y,
ListTop, ListLeft, ListBottom, ListRight,
LIST_QUERY_BASE_LINE, GRGetTextHeight("M"));
if (NewIndex + FirstDisplayed >= NumOfEntries)
NewIndex = -1;
if (NewIndex != MatchIndex) {
/* Invert this entry back to original state: */
if (MatchIndex >= 0)
GRXORRectangle(ListLeft - 1,
ListTop + MatchIndex * LIST_QUERY_BASE_LINE - 1,
ListRight + 1,
ListTop + GRGetTextHeight("M") + 1 +
MatchIndex * LIST_QUERY_BASE_LINE);
MatchIndex = NewIndex;
/* Invert this entry: */
if (MatchIndex >= 0)
GRXORRectangle(ListLeft - 1,
ListTop + MatchIndex * LIST_QUERY_BASE_LINE - 1,
ListRight + 1,
ListTop + GRGetTextHeight("M") + 1 +
MatchIndex * LIST_QUERY_BASE_LINE);
}
break;
}
if (!Exit) Event = IntrGetEventWait(&x, &y);
}
QueryEpilog(Cursor);
return RetVal;
}
/****************************************************************************
* Routine to display list of items in the given location and spacing: *
* All list and area is inverted once drawn. *
* If SizeOfItem = 0 then Items is assumed to point on array of (char *). *
****************************************************************************/
static void ListQueryDrawItems(char **StrEntries, int SizeOfEntry,
int NumOfEntries,
int FirstDisplayed, int NumOfDisplayedEntries,
int Left, int Top, int Right, int Bottom,
IntrColorType BackColor, IntrColorType ForeColor)
{
int i, Last, Color;
char
*String = (char *) StrEntries;
IntrAllocColor(BackColor, INTR_INTENSITY_HIGH);
GRSBar(Left - 2, Top, Right, Bottom + 1); /* -2, +1 because of shadow. */
Last = MIN(NumOfEntries, FirstDisplayed + NumOfDisplayedEntries);
Color = IntrAllocColor(ForeColor, INTR_INTENSITY_VHIGH);
GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
for (i = FirstDisplayed; i < Last; i++)
GRSTextShadow(Left, Top + (i - FirstDisplayed) * LIST_QUERY_BASE_LINE,
Color,
SizeOfEntry == 0 ? StrEntries[i] : &String[i * SizeOfEntry]);
}